package grpc

import (
	"TOScheduler/src/logger"
	"TOScheduler/src/pb"
	"TOScheduler/src/util"
	"context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
	"net"
	"strconv"
	"sync"
	"time"
)

type serverProfile struct{}

const (
	Method = "tcp"
)

var (
	log       = logger.GetLogger()
	chanCap   int
	timeoutAI time.Duration
	chRes     chan *pb.Res
	chFlag1   chan int
	chFlag2   chan int
	briefMap  sync.Map
	taskMap   sync.Map
)

func (s *serverProfile) SendBriefSDKTO(_ context.Context, brief *pb.ToTOBrief) (*pb.BackSDKBrief, error) {
	go SendProfileTSTD(brief)
	log.Debug("[gRPC TD->TS] Get channel!")
	// response
	res := pb.BackSDKBrief{
		Response: 1,
	}
	return &res, nil
}

func (s *serverProfile) SendTaskSDKTO(_ context.Context, task *pb.ToTOTask) (*pb.BackSDKTask, error) {
	if task.Basic[0].TaskType == pb.Basic_EP {
		Tran(task.Basic[0])
	} else {
		id, _ := strconv.Atoi(task.Basic[0].Id[:13])
		// insert timestamps
		start := util.GenTimestamp()
		for _, latency := range task.Latency {
			ts := latency.Timestamps
			ts = append(ts, start)
			latency.Timestamps = ts
		}
		taskMap.Store(id, task)
		chFlag2 <- id
	}
	// empty checking
	log.Debug("[gRPC SDK->TS] Get channel!")
	// response
	select {
	case value := <-chRes:
		res := pb.BackSDKTask{
			Res: value,
		}
		return &res, nil
	case <-time.After(time.Second * timeoutAI):
		res := pb.BackSDKTask{
			Res: nil,
		}
		return &res, nil
	}
}

func StartSDKServer(serverSocket string, capacity int, tmo int) {
	// listening network port
	listener, err := net.Listen(Method, serverSocket)
	if err != nil {
		return
	}
	// initialize timeoutAI
	timeoutAI = time.Duration(tmo)
	// initialize channels
	chanCap = capacity
	chRes = make(chan *pb.Res, chanCap)
	chFlag1 = make(chan int, chanCap)
	chFlag2 = make(chan int, chanCap)
	// open gRPC service
	s := grpc.NewServer()
	pb.RegisterSendMsgSDKTOServer(s, &serverProfile{})
	reflection.Register(s)
	log.Info("[gRPC SDK] started successfully")
	err = s.Serve(listener)
	if err != nil {
		return
	}
}
